package asteroids.model.programs.statement;

import java.util.*;

import asteroids.model.programs.expression.*;
import asteroids.model.programs.type.*;


public class Sequence extends S {
	
	private List<S> statements;
	private int currentPlace;

	public Sequence(int line, int column, List<S> statements) {
		super(line, column);
		this.statements = statements;
		currentPlace = 0;
	}

	public List<S> getList(){
		return statements;
	}
	
	public void execute(T type){
	}

	@Override
	public S getNextStatement(){
		if(!hasSteps()) //no steps, nothing to return...
			return null;
		S next = statements.get(currentPlace).getNextStatement();
		while(next == null || next.hasBeenExecuted()){
			currentPlaceIncrement();
			next = statements.get(currentPlace).getNextStatement();
		}
		return next;
	}

	private void currentPlaceIncrement(){
		currentPlace++;
		if(currentPlace == statements.size()){
			currentPlace = 0;
		}
	}
	
	@Override
	public boolean hasSteps() {
		for(S statement: statements){
			if(statement.hasSteps())
				return true;
		}
		return false;
	}

	@Override
	public boolean hasBeenExecuted(){
		if(!hasSteps()) //no steps, nothing to execute, so has been executed
			return true;
		else{
			return getLastStatement().hasBeenExecuted();
		}
	}
	
	@Override
	public void setExecuted(boolean b){
		super.setExecuted(b);
		for(S s : statements)
			s.setExecuted(b);
		currentPlace = 0;
	}
	
	@Override
	public S getFirstStatement(){
		if(!hasSteps())
			return null;
		else{
			return statements.get(0).getFirstStatement();
		}
	}
	
	@Override
	public S getLastStatement(){
		if(!hasSteps())
			return null;
		else{
			int i = statements.size()-1;
			S s = statements.get(i);
			while((s instanceof Sequence && !s.hasSteps()) || s.getLastStatement() == null){
				i--;					//if its an empty sequence, take the previous statement
				s = statements.get(i);	//if s.getLastStatement() == null, we continue, 
			}							// because we are looking for a real statement, and we know
			return s.getLastStatement();// that there is one (hasSteps())
		}
	}
	
	@Override
	public ArrayList<E> getExpressions(){
		ArrayList<E> list = new ArrayList<E>();
		for(S s : statements)
			list.addAll(s.getExpressions());
		return list;
	}
	
	public ArrayList<VariableExpression> getVariableExpressions(){
		ArrayList<VariableExpression> list = new ArrayList<VariableExpression>();
		for(S statement: statements){
			list.addAll(statement.getVariableExpressions());
		}
		return list;
	}
	
	public String typecheck(Map<String, T> globals){
		String returnString = "";
		for(S statement: statements){
			returnString = returnString + statement.typecheck(globals);
		}
		return returnString;
	}
	
	public boolean hasAction(){
		for(S s: statements){
			if(s.hasAction())
				return true;
		}
		return false;
	}
}
